#include "hspell.h"
#include <QDebug>
#include <QRegExp>



//--------------------------------------------------
/**
 * @brief HSpell::HSpell
 */

HSpell::HSpell () : QSettings ("PapaJaac", "hspell")
{

    if (! QDir (dicPath ()).exists ()) {
        QDir dir;
        dir.mkpath (dicPath ());
    }

    QString affDest (QString ("%1%2.aff")
                     .arg (dicPath ())
                     .arg (currentAff ()));

    if (! QFile (affDest).exists ())
    {
        setCurrentAff ("fr-classique+reforme1990");
        QString affSrc (":/hdics/fr-classique+reforme1990.aff");
        QFile::copy (affSrc, affDest);
        QFile::setPermissions (affDest, QFile::ReadUser| QFile::WriteUser);
        affDest = QString ("%1%2.aff")
                  .arg (dicPath ())
                  .arg (currentAff ());
    }

    QString dicDest (QString ("%1%2.dic")
                     .arg (dicPath ())
                     .arg (currentDic ()));

    if (! QFile (dicDest).exists ()) {
        setCurrentDic ("fr-classique+reforme1990");
        QString dicSrc (":/hdics/fr-classique+reforme1990.dic");
        QFile::copy (dicSrc, dicDest);
        QFile::setPermissions (dicDest, QFile::ReadUser| QFile::WriteUser);
        dicDest = QString ("%1%2.dic")
                  .arg (dicPath ())
                  .arg (currentDic ());
    }

    m_handle = Hunspell_create (affDest.toUtf8 ().constData (), dicDest.toUtf8 ().constData ());

}
//-------------------------------------
/**
 * @brief HSpell::spell
 * @param word
 * @return
 */
int HSpell::spell (const QString &word)
{
    return Hunspell_spell (m_handle, word.toUtf8 ().constData ());
}
//-------------------------------------------
/**
 * @brief HSpell::isUnknown
 * @param word
 * @return bool
 */
bool HSpell::isMisspelled (const QString &word)
{
    return word.length () > 1 && !word.contains (' ') && spell (word) == 0;
}
//-------------------------------
/**
 * @brief HSpell::dicList
 * @return QStringList
 */
QStringList HSpell::dicList ()
{
    QDir dir (dicPath ());

    QStringList filters;
    filters << "*.dic";
    dir.setNameFilters(filters);
    QFileInfoList list (dir.entryInfoList ());

    QStringList result;
    foreach (QFileInfo info, list)
        result << info.baseName ();

    return result;
}
//-----------------------------------------------
/**
 * @brief HSpell::analyse
 * @param word
 * @return
 */
QStringList HSpell::analyse (const QString& word)
{
    char** slst;
    int count = Hunspell_analyze (m_handle, &slst, word.toUtf8 ().constData ());
    QStringList result;

    for (int indice = 0 ; indice < count ; indice++)
    {
        result << QString (slst [indice]);
    }
    return result;
}
//---------------------------------------------
/**
 * @brief HSpell::stem
 * @param word
 * @return
 */
QStringList HSpell::stem (const QString& word)
{
    char** slst;
    int count = Hunspell_stem (m_handle, &slst, word.toUtf8 ().constData ());
    QStringList result;

    for (int indice = 0 ; indice < count ; indice++) {
        result << QString (slst [indice]);
    }
    return result;
}
//----------------------------------------------
QStringList HSpell::stem2 (const QString& /*word*/)
{
    return QStringList () << "**NOT IMPLEMENTED**";

//	QStringList list (analyse (word));

//	QList <QByteArray> baList;

//	foreach (const QString & w, analyse (word)) {
//		baList << w.toUtf8 ();
//	}

//	const int n = list.size ();

//	const char* desc [n];

//	for (int indice = 0 ; indice < n ; indice++) {
//		desc [indice] = baList.at (indice).constData ();
//	}

//	char ** slst;
//	int count = 0;

//	int ret = Hunspell_stem2 (m_handle, &slst, &desc, n);
//	QStringList result;

//	for (int indice = 0 ; indice < count ; indice++) {
//		result << QString (slst [indice]);
//	}
//	return result;

}
//---------------------
void HSpell::generate()
{
    //	int result = Hunspell_generate (m_handle, slst, word, word2);
}
//------------------------
void HSpell::generate2 ()
{
    //	int result = Hunspell_generate2 (m_handle, slst, word, desc, n);
}
//-------------------------------------
void HSpell::add (const QString& word)
{
    Hunspell_add (m_handle, word.toUtf8 ().constData ());
}
//---------------------------
void HSpell::addWithAffix ()
{
    //	int result = Hunspell_add_with_affix (m_handle, word, example);
}
//----------------------------------------
/**
 * @brief HSpell::remove
 * @param word
 */
void HSpell::remove (const QString& word)
{
    Hunspell_remove (m_handle, word.toUtf8 ().constData ());
}
//---------------------------
// SETTINGS
//---------------------------

/**
 * @brief HSpell::currentDic
 * @return
 */
QString HSpell::currentDic ()
{
    return value ("currentDic", QString ("fr-classique+reforme1990")).toString ();
}
//--------------------------------------------
/**
 * @brief HSpell::setCurrentDic
 * @param dic
 */
void HSpell::setCurrentDic (const QString &dic)
{
    setValue ("currentDic", dic);
}
//---------------------------
/**
 * @brief HSpell::currentAff
 * @return
 */
QString HSpell::currentAff ()
{
    return value ("currentAff", QString ("fr-classique+reforme1990")).toString ();
}
//--------------------------------------------
/**
 * @brief HSpell::setCurrentAff
 * @param aff
 */
void HSpell::setCurrentAff (const QString &aff)
{
    setValue ("currentAff", aff);
}
//----------------------------------------------------
/**
 * @brief HSpell::suggestionsFor
 * @param word
 * @return
 */
QStringList HSpell::suggestionsFor (const QString &word)
{
    QStringList result;
    if (! word.isEmpty ()) {
        char ** slst;
        int count = Hunspell_suggest (m_handle, &slst, word.toUtf8 ().constData ());

        for (int indice = 0 ; indice < count ; indice++) {
            result << QString (slst [indice]);
        }
    }

    result.sort ();

    return result;
}
//---------------------------------
/**
 * @brief HSpell::misspelledWords
 * @param text
 * @return
 */
QStringList HSpell::misspelledWords (const QString &text)
{
    QStringList result;

    foreach (const QString& word, wordList (text).values ()) {
        if (isMisspelled (word)) {
            result << word;
        }
    }

    result.removeDuplicates ();


    return result;
}

QMap <int, QString> HSpell::wordList (const QString& text)
{
    QString allowedChars;
    for (char car = 'a' ; car <= 'z' ; car++) {
        allowedChars += car;
    }
    allowedChars += "àäâéëèêïîöôùüûÿœæç";
    allowedChars += allowedChars.toUpper ();

    if (true) {	// pas implémenté : en fait si on accepte les chiffres dans les mots
        allowedChars += "0123456789";
    }

    QMap <int, QString> result;
    QChar lastCar;
    QString currentWord;
    const int len = text.length ();

    int wordStart = 0;
    for (int index = 0 ; index < len ; index++) {
        const QChar& currentCar = text.at (index);
        if (allowedChars.contains (currentCar)) {
            if (currentWord.isEmpty ()) {
                wordStart = index;
            }
            currentWord += currentCar;
            if (index == len - 1 && !currentWord.isEmpty ()) {
                result.insert (wordStart, currentWord);
                currentWord.clear ();
            }
        }
        else {
            // fin d'un mot
            if (!currentWord.isEmpty ()) {
                if (currentCar.unicode () == '\'') {
                    qDebug () << "Apostrophe détectée !";
                    currentWord += currentCar;
                }
                result.insert (wordStart, currentWord);
                currentWord.clear ();
            }
        }
        lastCar = currentCar;
    }

    qDebug () << text << result;

    return result;
    //	const QString accents ("a-zA-Z0-9àäâéëèêïîöôùüûÿœæçÀÄÂÉËÈÊÏÎÖÔÙÜÛŸŒÆÇ");
    //	const QString re (QString ("[%1]+(-+[%1]+)*").arg (accents));

    //	QRegExp	regexp (re);
    //	int pos = 0;

    //	QStringList result;

    //	while ((pos = regexp.indexIn (text, pos)) >= 0 ) {
    //		const QString& tmpWord (regexp.cap (0));
    //		result << tmpWord;
    //		pos += tmpWord.length ();
    //	}
    //	qDebug () << text << result;

    //	return result;
}
